package com.snopy.concurrency.atomic;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * @author snopy
 * @version 1.0.0
 * @classname ArrayDemo
 * @description
 * @email 77912204@qq.com
 * @date 2022/06/28 17:13
 */
public class ArrayDemo {

    public static void main(String[] args) {
                demo(()->new int[10],
                     array->array.length,
                     (array,index)->array[index]++,
                     array->System.out.println(Arrays.toString(array)));
                demo(()->new AtomicIntegerArray(10),
                        AtomicIntegerArray::length,
                        AtomicIntegerArray::getAndIncrement,
                array->System.out.println(array.toString()));
    }

    /*
    * 参数1：提供数组、可以是线程不安全数组或线程安全数组
    * 参数2：获取数组长度的方法
    * 参数3：自增方法，回传array,index
    * 参数4：打印数组的方法
    * */
    private static <T> void demo(Supplier<T> arraySupplier,
                                 Function<T,Integer> lengthFun,
                                 BiConsumer<T,Integer> putConsumer,
                                 Consumer<T> printConsumer
                                 ){
        List<Thread> ts = new ArrayList<>();
        T array = arraySupplier.get();
        int length = lengthFun.apply(array);
        for (int i = 0; i < length; i++) {
            ts.add(new Thread(()->{
                for (int j = 0; j < 10000; j++) {
                    putConsumer.accept(array,j%length);
                }
            }));
        }
        ts.forEach(Thread::start);
        ts.forEach(t->{
            try{
                t.join();
            }catch (InterruptedException ignored){}
        });
        printConsumer.accept(array);
    }
}
